package com.dmxtechnologies.community.rar.outbound;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Set;
import java.util.logging.Logger;

import javax.naming.NamingException;
import javax.naming.Reference;
import javax.resource.Referenceable;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.spi.ConnectionDefinition;
import javax.resource.spi.ConnectionManager;
import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionFactory;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.ResourceAdapterAssociation;
import javax.security.auth.Subject;

import com.dmxtechnologies.community.rar.DMXCMSResourceAdapter;


/* The container's connection manager uses this class to create a pool
 * of managed connections, which are associated at times with physical ones */

/* Define classes an interfaces for the EIS physical connection */
@ConnectionDefinition(
    connectionFactory = ConnectionFactory.class,
    connection = Connection.class,
    connectionFactoryImpl = CMSConnectionFactoryImpl.class,
    connectionImpl = CMSConnectionImpl.class
)
public class CMSManagedConnectionFactory implements ManagedConnectionFactory,
                                                      ResourceAdapterAssociation,
                                                      Serializable,
                                                      Referenceable {
    
    private static final Logger log = Logger.getLogger("CMSManagedConnectionFactory");
    private static final long serialVersionUID = 7918855339952421358L;
    private ResourceAdapter ra;
    private Reference reference;
    private PrintWriter logWriter;
    
    public CMSManagedConnectionFactory() { }
    
	@Override
	public Object createConnectionFactory() throws ResourceException {
		log.info("[CMSManagedConnectionFactory] createConnectionFactory()-NM");
		/* Non-managed connections not supported */
		return null;
	}
    
    /* The application server provides a connection manager */
    @Override
    public Object createConnectionFactory(ConnectionManager cxManager) 
                                          throws ResourceException {
        log.info("[CMSManagedConnectionFactory] createConnectionFactory()");
        return new CMSConnectionFactoryImpl(this, cxManager);
    }

    /* Called by the application server to create a managed connection */
    @Override
    public ManagedConnection createManagedConnection(Subject subject, 
                                                     ConnectionRequestInfo cxRequestInfo) 
                                                     throws ResourceException {
        log.info("[CMSManagedConnectionFactory] createManagedConnection()");
        try {
        	DMXCMSResourceAdapter adapter = (DMXCMSResourceAdapter) getResourceAdapter();
            return new CMSManagedConnection(adapter.getHost(),adapter.getPort(),adapter.getProjectName(),adapter.getInterfaceName());
        } catch (IOException e) {
            throw new ResourceException(e.getCause());
        }
    }

    /* When an application requests a connection, provide an existing one
     * from the pool if it matches the connection parameters */
    @SuppressWarnings("rawtypes")
	@Override
    public ManagedConnection matchManagedConnections(Set connectionSet, 
                                                     Subject subject, 
                                                     ConnectionRequestInfo cxRequestInfo) 
                                                     throws ResourceException {
        log.info("[CMSManagedConnectionFactory] matchManagedConnections()");
        /* This resource adapter does not use security (Subject) */
        CMSManagedConnection match = null;
        /* This resource adapter has no additional parameters for connections,
         * so any open connection can be used by an application */
        for (Object mco : connectionSet) {
            if (mco != null) { 
                match = (CMSManagedConnection) mco;
                log.info("Connection match!");
                break;
            }
        }
        return match;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws ResourceException {
        this.logWriter = out;
    }
    @Override
    public PrintWriter getLogWriter() throws ResourceException {
        return logWriter;
    }

    /* Called by the server to associate this object with the resource adapter */
    @Override
    public ResourceAdapter getResourceAdapter() {
        return ra;
    }
    @Override
    public void setResourceAdapter(ResourceAdapter ra) throws ResourceException {
        this.ra = ra;
    }

    /* Called by the server to associate an RA with a JNDI resource name.
     * Applications access an RA via JNDI resource injection (@Resource) */
    @Override
    public void setReference(Reference reference) {
        this.reference = reference;
    }
    @Override
    public Reference getReference() throws NamingException {
        return reference;
    }
    
}
